package chapter9.homework;

import java.io.*;
import java.time.LocalDateTime;
import java.util.*;

//学生信息管理系统
public class StudentInfoSys {
    // 创建一个Scanner对象
    private static final Scanner sc = new Scanner(System.in);
    // 新增静态集合来存储学生信息
    private static final List<Student> studentList = new ArrayList<>();
    // 学生类
    static class Student implements Serializable {
        private String id;
        private String name;
        private Double chinese;
        private Double math;
        private Double english;
        private Double sum;
        private LocalDateTime dateTime;

        // 新增getter和setter方法
        public String getId() {
            return id;
        }

        public void setId(String id) {
            this.id = id;
        }

        public String getName() {
            return name;
        }

        public void setName(String name) {
            this.name = name;
        }

        public Double getChinese() {
            return chinese;
        }

        public void setChinese(Double chinese) {
            this.chinese = chinese;
        }

        public Double getMath() {
            return math;
        }

        public void setMath(Double math) {
            this.math = math;
        }

        public Double getEnglish() {
            return english;
        }

        public void setEnglish(Double english) {
            this.english = english;
        }

        public Double getSum() {
            return sum;
        }

        public void setSum(Double sum) {
            this.sum = sum;
        }

        public LocalDateTime getDateTime() {
            return dateTime;
        }

        public void setDateTime(LocalDateTime dateTime) {
            this.dateTime = dateTime;
        }

        public String toString() {
            return "学生id:" + id + "\t学生姓名：" + name + "\t语文成绩:" + chinese + "\t数学成绩:" + math + "\t英语成绩:" + english + "\t总分:" + sum + "\t收录时间:" + dateTime;
        }
    }
    // 主菜单显示方法
    public static void MainMenu() {
        System.out.println();
        System.out.println("    |-----------学生信息管理系统-----------|");
        System.out.println("    |                                   |");
        System.out.println("    |         1. 录入学生信息             |");
        System.out.println("    |         2. 查找学生信息             |");
        System.out.println("    |         3. 删除学生信息             |");
        System.out.println("    |         4. 修改学生信息             |");
        System.out.println("    |         5. 插入学生信息             |");
        System.out.println("    |         6. 排序                    |");
        System.out.println("    |         6. 排序所有学生             |");
        System.out.println("    |         7. 统计学生总数             |");
        System.out.println("    |         8. 显示所有学生信息          |");
        System.out.println("    |         0. 退出系统                |");
        System.out.println("    |                                   |");
        System.out.println("    |-----------------------------------|");
        System.out.println("              请选择(0-8):");
    }

        // 输入2后查找学生信息的子菜单及其实现方法
        public static void Menu2() {

            InfoLoop: while (true){
                System.out.println();
                System.out.println("    |-----------学生信息管理系统-----------|");
                System.out.println("    |                                   |");
                System.out.println("    |         21. 查询学生信息            |");
                System.out.println("    |         22. 多行结果查询            |");
                System.out.println("    |         23. 模糊查询姓名            |");
                System.out.println("    |         21. 按学号精确查询           |");
                System.out.println("    |         22. 总分分数线查询           |");
                System.out.println("    |         23. 姓名模糊查询            |");
                System.out.println("    |         20. 返回上级               |");
                System.out.println("    |                                   |");
                System.out.println("    |-----------------------------------|");
                System.out.println("              请选择(20-23):");
                String QueryChoice = sc.next();
                switch(QueryChoice) {
                    case "21": {
                        // 同学们可以在这里编写自己的查询函数逻辑
                        // 不过更建议放到子函数里面
                        System.out.println("查询学生信息");
                        searchStudentInfo();
                        break;
                    }
                    case "22": {
                        // 总分分数线查询的意思，是输入一个分数线，把高于这个分数线的学生信息显示出来
                        System.out.println("多行结果查询/总分分数线查询");
                        ScoreLineQuery();
                        break;
                    }
                    case "23": {
                        System.out.println("模糊查询姓名");
                        FuzzyNameQuery();
                        break;
                    }
                    case "20": {
                        System.out.println("返回上级");
                        break InfoLoop;
                    }
                    default: {
                        System.out.println("输入错误，请重新输入(20-23)");
                        break;
                    }
                }
            }
        }
        //输入6后的排序菜单及其实现方法
        public static void Menu6() {
            SortLoop:while (true){
                System.out.println();
                System.out.println("    |-----------学生信息管理系统-----------|");
                System.out.println("    |                                   |");
                System.out.println("    |         61. 按总分降序排            |");
                System.out.println("    |         62. 选择法总分排            |");
                System.out.println("    |         62. 按总分升序排            |");
                System.out.println("    |         63. 按时间降序排            |");
                System.out.println("    |         60. 返回上级               |");
                System.out.println("    |                                   |");
                System.out.println("    |-----------------------------------|");
                System.out.println("              请选择(60-63):");
                String SortChoice = sc.next();

                switch(SortChoice) {
                    case "61": {
                        System.out.println("按总分降序排");
                        SumDownSort();
                        break;
                    }
                    case "62": {
                        System.out.println("选择法总分排");
                        SumUpSort();
                        break;
                    }
                    case "63": {
                        System.out.println("按时间降序排");
                        DateTimeSort();
                        break;
                    }
                    case "60": {
                        System.out.println("返回上级");
                        break SortLoop;
                    }
                    default: {
                        System.out.println("输入错误，请重新输入");
                    }
                }
            }
        }
    //主菜单及子菜单实现方法
    public static void main(String[] args) {
        load();
        Loop: while (true){
            MainMenu();
            //通过键盘输入选项
            String choice = sc.next();
            switch(choice) {
                case "1": {
                    System.out.println("录入学生信息");
                    inputStudentInfo();
                    break;
                }
                case "2": {
                    System.out.println("查找学生信息");
                    Menu2();
                    break;
                }
                case "3": {
                    System.out.println("删除学生信息");
                    deleteStudentInfo();
                    break;
                }
                case "4": {
                    System.out.println("修改学生信息");
                    modifyStudentInfo();
                    break;
                }
                case "5": {
                    System.out.println("插入学生信息");
                    insertStudentInfo();
                    break;
                }
                case "6": {
                    System.out.println("排序学生信息");
                        Menu6();
                    break;
                }
                case "7": {
                    System.out.println("统计学生总数");
                    countStudents();
                    break;
                }
                case "8": {
                    System.out.println("显示所有学生信息");
                    displayAllStudents();
                    break;
                }
                //退出系统顺便保存
                case "0": {
                    save();
                    System.out.println("感谢使用，再见！");
                    break Loop;
                }
                default: {
                    System.out.println("输入错误，请重新输入");
                    break;
                }
            }
        }
    }
    //录入学生信息
    private static void inputStudentInfo() {
        Student student = new Student();
        System.out.println("--- 录入学生信息 ---");

        System.out.print("请输入学号: ");
        String id = sc.next();
        // 判断学号是否重复
        if(getIndex(studentList, id) != null) {
            System.out.println("学号重复，请重新输入");
            inputStudentInfo();
            return;
        }
        student.setId(id);

        System.out.print("请输入姓名: ");
        student.setName(sc.next());

        System.out.print("请输入语文成绩: ");
        student.setChinese(sc.nextDouble());

        System.out.print("请输入数学成绩: ");
        student.setMath(sc.nextDouble());

        System.out.print("请输入英语成绩: ");
        student.setEnglish(sc.nextDouble());

        // 计算总分
        student.setSum(student.getChinese() + student.getMath() + student.getEnglish());

        // 设置当前时间为录入时间
        student.setDateTime(LocalDateTime.now());

        // 将学生对象添加到集合中
        studentList.add(student);
        System.out.println("学生信息录入成功!");
        System.out.println(student);
    }
    //输入21：查找学生信息
    private static void searchStudentInfo(){
        //如果没有学生信息
        if (studentList.size() == 0) {
            System.out.println("当前无学生信息，请添加后再查询");
            return;
        }
        System.out.println("请输入要查找的id");
        String id = sc.next();
        //遍历集合寻找符合该id的学生信息
        for(Student i :  studentList) {
            if (i.getId().equals(id)) {
                System.out.println("查找到学生信息：\n" + i);
                return;
            }
        }
        //如果没有找到
        System.out.println("没有找到该id对应的学生信息");
    }
    //删除学生信息
    private static void deleteStudentInfo() {
        if (studentList.size() == 0) {
            System.out.println("当前无学生信息，请添加后再删除");
            return;
        }
        // 指定一个学生 id 然后完成从集合里删除。
        System.out.println("请输入要删除的id");
        String id = sc.next();
        // 遍历找到  id 的学生位置，然后删除
        // 可以考虑使用 List 的 remove(int index) 方法，在指定位置删除元素
        /**for (int i = 0; i < studentList.size(); i++) {
            if (studentList.get(i).getId().equals(id)) {
                studentList.remove(i);
                System.out.println("删除成功！");
                return;
            }//for遍历
        }*/
        //用getIndex()
        Student index = getIndex(studentList, id);
        if (index != null) {
            studentList.remove(index);
            System.out.println("id为"+ id +"的学生删除成功！");
            return;
        }
        // 注意如果 id 不存在，则提示用户 id 不存在。
        System.out.println("没有找到该id对应的学生信息");
    }
    //显示所有学生信息
    private static void displayAllStudents() {
        if (studentList.isEmpty()) {
            System.out.println("当前没有学生信息");
            return;
        }
        System.out.println("--- 所有学生信息 ---");
        //调整表头格式，考虑中文字符宽度
        printTitle();
        for (Student student : studentList) {
            System.out.println(student);
        }
        printFooter();
        System.out.println("共 " + studentList.size() + " 条记录");
    }
    //修改学生信息功能
    private static void modifyStudentInfo() {
        // 给用户发提示： 输入 id，然后修改对应学生的信息。
        System.out.println("请输入要修改的id");
        String id = sc.next();
        // 用getIndex()省略遍历
        Student student = getIndex(studentList, id);
        // 可以考虑使用 List 的 set(int index, E element) 方法，在指定位置修改元素
        if (student != null) {
            System.out.println("当前学生信息：\n" + student);
            // 开始修改各个字段
            System.out.print("请输入新的姓名");
            student.setName(sc.next());
            System.out.print("请输入新的语文成绩");
            student.setChinese(sc.nextDouble());
            System.out.print("请输入新的数学成绩");
            student.setMath(sc.nextDouble());
            System.out.print("请输入新的英语成绩");
            student.setEnglish(sc.nextDouble());
            // 重新计算总分
            student.setSum(student.getChinese() + student.getMath() + student.getEnglish());
            // 更新录入时间为当前时间
            student.setDateTime(LocalDateTime.now());
            // 使用 set 方法更新集合中的学生信息
            studentList.set(studentList.indexOf(student), student);//有一说一啊，这个写了跟没写效果一样啊🤔🤔🤔

            System.out.println("学生信息修改成功！");
            return;
        }
        // 如果没有找到，则提示用户 id 不存在
        System.out.println("未找到该学生");
    }
    //分数线查询
    private static void ScoreLineQuery() {
        if (studentList.isEmpty()) {
            System.out.println("当前没有学生信息");
            return;
        }
        //  输入分数线
        System.out.println("请输入要查询的分数线");
        double scoreLine = sc.nextDouble();
        List<Student> result = new ArrayList<>();
        for (Student student : studentList) {
            if (student.getSum() >= scoreLine) {
                result.add(student);
            }
        }
        if (result.isEmpty()) {
            System.out.println("没有成绩线为" + scoreLine + "以上的学生");
            return;
        }
        printTitle();
        for (Student student : result) {
            System.out.println(student);
        }
        printFooter();
        System.out.println("共 " + result.size() + " 条记录");
    }
    //模糊姓名查询🥰🥰🥰
    private static void FuzzyNameQuery() {
        //System.out.println("我不会，长大后再学\uD83E\uDD70\uD83E\uDD70\uD83E\uDD70~~~");//嘻嘻，我不会🥰🥰🥰
        if(studentList.isEmpty()) {
            System.out.println("当前没有学生信息");
            return;
        }
        System.out.println("请输入要查询的姓名所包含的关键字：");
        String keyword = sc.next();
        List<Student> result = new ArrayList<>();
        for (Student student : studentList) {
            if (student.getName().contains(keyword)) {
                result.add(student);
            }
        }
        if(result.isEmpty()) {
            System.out.println("没有姓名包含" + keyword + "的学生");
            return;
        }
        printTitle();
        for (Student student : result) {
            System.out.println(student);
        }
        printFooter();
        System.out.println("共 " + result.size() + " 条记录");
    }
    //统计学生总数
    private static void countStudents() {
        if (studentList.isEmpty()) {
            System.out.println("当前没有学生信息");
            return;
        }
        System.out.println("当前共有"+studentList.size()+"位同学的信息");
    }
    //插入学生信息
    private static void insertStudentInfo() {
        if(studentList.isEmpty()){
            System.out.println("当前没有学生信息，请添加后再插入");
        }
        System.out.println("请输入你要插入的学号的前一个学号");
        String perviousId = sc.next();
        Student index = getIndex(studentList, perviousId);
        if (index != null) {
            Student student = new Student();
            //公式の水代码行数
            System.out.println("请输入学号");
            String id = sc.next();
            //判断学号是否已存在
            if(getIndex(studentList, id) != null){
                System.out.println("该学号已存在");
                insertStudentInfo();
                return;
            }
            student.setId(id);
            System.out.println("请输入姓名");
            student.setName(sc.next());
            System.out.println("请输入语文成绩");
            student.setChinese(sc.nextDouble());
            System.out.println("请输入数学成绩");
            student.setMath(sc.nextDouble());
            System.out.println("请输入英语成绩");
            student.setEnglish(sc.nextDouble());
            student.setSum(student.getChinese() + student.getMath() + student.getEnglish());
            student.setDateTime(LocalDateTime.now());
            //在指定位置插入新对象
            studentList.add(studentList.indexOf(index)+1, student);
            System.out.println(student);
            System.out.println("学生信息插入成功！");
            return;
        }
        System.out.println("未找到该学生");
    }
    //总分升序排序
    private static void SumUpSort() {
        if (studentList.isEmpty()) {
            System.out.println("当前没有学生信息");
            return;
        }
        /**Collections.sort(studentList, (o1, o2) -> o1.getSum().compareTo(o2.getSum()));*/ //网上找的简化代码
        Collections.sort(studentList, new Comparator<Student>() {
            @Override
            public int compare(Student s1, Student s2) {
                //如果s1的总分小于s2，则返回负数，表示s1应该排在前面
                return s1.getSum().compareTo(s2.getSum());
            }
        });
        printTitle();
        for (Student student : studentList) {
            System.out.println(student);
        }
        printFooter();
    }
    //总分降序排序(高到低
    private static void SumDownSort() {
        if (studentList.isEmpty()) {
            System.out.println("当前没有学生信息");
            return;
        }
        //
        Collections.sort(studentList, (o1, o2) -> o2.getSum().compareTo(o1.getSum()));
        printTitle();
        for (Student student : studentList) {
            System.out.println(student);
        }
        printFooter();
    }
    //录入时间排序
    private static void DateTimeSort() {
        if (studentList.isEmpty()) {
            System.out.println("当前没有学生信息");
            return;
        }
        Collections.sort(studentList, new Comparator<Student>() {
            @Override
            public int compare(Student o1, Student o2) {
                return o2.getDateTime().compareTo(o1.getDateTime());
            }
        });
        printTitle();
        for (Student student : studentList) {
            System.out.println(student);
        }
        printFooter();
    }
    // 调整字段宽度，学号14(中文字符7个)，姓名6(中文字符3个)，时间28

        public static void printFooter() {
            System.out.println("+----------------+------------+--------+--------+--------+--------+-------------------------------+");
        }


    /**
     * 我们把输出的格式封装成方法，便于在菜单8打印全部，以及菜单2查询部分时候打印，这样输出的格式保持一致。
     */
    public static void printTitle() {
        System.out.println("+----------------+------------+--------+--------+--------+--------+-------------------------------+");
        System.out.println("|      学号       |    姓名    |  语文   |  数学   |  英语   |  总分   |          录入时间              |");
        System.out.println("+----------------+------------+--------+--------+--------+--------+-------------------------------+");
    }
    //getIndex遍历简化代码（偷懒喽。。。
    public static Student getIndex(List<Student> studentList, String id) {
        for(Student i :  studentList) {
            if (i.getId().equals(id)) {
                return i;//找到相对应的元素，返回
            }
        }
        //遍历完所有元素都没找到，返回null
        return null;
    }
    //保存
    private static void save() {
        System.out.println("保存数据到文件...");
        try (ObjectOutputStream oos = new ObjectOutputStream(new FileOutputStream("students.dat"))) {
            oos.writeObject(studentList);
            System.out.println("数据保存成功！");
        } catch (IOException e) {
            System.err.println("保存数据时发生错误: " + e.getMessage());
        }
    }
    //读取
    private static void load() {
        File file = new File("students.dat");
        if (file.exists()) {
            try (ObjectInputStream ois = new ObjectInputStream(new FileInputStream(file))) {
                studentList.addAll((List<Student>) ois.readObject());
            } catch (IOException | ClassNotFoundException e) {
                System.err.println("学生数据丢失");
            }
        }
    }
}
